package com.pipayshop.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.pipayshop.entity.*;

import com.pipayshop.entity.dto.LoginDTO;
import com.pipayshop.entity.dto.RegisterDTO;
import com.pipayshop.entity.dto.UserRegisterDTO;
import com.pipayshop.entity.vo.*;
import com.pipayshop.exception.BusinessException;
import com.pipayshop.mapper.*;
import com.pipayshop.service.UserInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pipayshop.utils.*;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;

/**
 * <p>
 * 用户数据表 服务实现类
 * </p>
 *
 * @author kk
 * @since 2024-09-08
 */
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {
    private static final String REGISTER_FALSE = "registration_failed";
    private static final String LOGIN_FALSE = "login_failed";
    @Resource
    private UserInfoMapper userInfoMapper;
    @Resource
    private UserRegisterMapper userRegisterMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private ItemInfoMapper itemInfoMapper;
    @Resource
    ImageMapper imageMapper;
    @Resource
    private UserShopInfoMapper shopInfoMapper;
//    @Autowired
//    private OnlineStoreShopMapper shopMapper;
    @Resource
    private UserAccountInfoMapper accountInfoMapper;

    private Searcher searcher;

    @Resource
    private LoginRecordMapper loginRecordMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResultVO login(LoginDTO loginDTO) {
        if (loginDTO == null){
            throw new BusinessException("invalid_parameter");
        }
        // 根据pi_name查询数据库
        UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>()
                .eq(UserInfo::getUserName, loginDTO.getUserName()));
        if (userInfo == null) {
            // 新用户注册流程
            UserInfo newUser = new UserInfo();
            // 属性转移
            String username = loginDTO.getUserName();
            newUser.setPiName(username);
            newUser.setUserName(username);
            newUser.setAccessToken("123456789");
            newUser.setUid(username);
            newUser.setUserImage(null);
            // 生成HD 地址
            String walletAddress = HDWalletGenerator.generateHDWallet(userInfo.getId());
            newUser.setWalletAddress(walletAddress);
            // 插入数据
            int insert = userInfoMapper.insert(newUser);
            // 创建用户账号
            insert += accountInfoMapper.createAccount(username);
            // 记录登录
            String ip = getIp();
            String region = getIp2Region(ip);
            LoginRecord loginRecord = new LoginRecord(username, ip, region, new Date(), username);
            loginRecordMapper.insert(loginRecord);

            if (insert < 2) {
                throw new BusinessException(REGISTER_FALSE);
            }

            // 给新用户开设网店
            UserShopInfo shopInfo = new UserShopInfo(
                    null,                          // id (自增，不需要传入)
                    StringUtil.generateShortId(),  // shopId
                    username,                      // shopName
                    null,                          // tagList
                    null,                          // score
                    null,                          // shopIntroduce
                    null,                          // shopImagList
                    null,                          // categoryId
                    username,                      // uid
                    0,                             // status
                    0,                             // membership
                    Constants.AVATAR_IMAG,         // avatar
                    null,                          // piAddress
                    0                               // level
            );

            int insert1 = itemInfoMapper.insert(shopInfo);
            if (insert1 < 1) {
                log.error("给新用户开一家网店失败");
                throw new BusinessException(REGISTER_FALSE);
            }

            String jwt = JwtUtil.createJWT(username);
            // 把token响应给前端
            HashMap<String, Object> map = new HashMap<>();
            map.put("token", jwt);
            map.put("user", newUser);
            return new ResponseResultVO(200, "登陆成功", map);
        }

        // 已有用户，生成 JWT 并返回

        if (userInfo.getWalletAddress() == null) {
            // 创建HD地址
            String walletAddress = HDWalletGenerator.generateHDWallet(userInfo.getId());
            userInfo.setWalletAddress(walletAddress);
            int insert = userInfoMapper.updateById(userInfo);
            if (insert < 1) {
                throw new BusinessException(LOGIN_FALSE);
            }
        }

        String jwt = JwtUtil.createJWT(userInfo.getUserName());
        // 把token响应给前端
        HashMap<String, Object> map = new HashMap<>();
        map.put("token", jwt);
        map.put("user", userInfo);
        return new ResponseResultVO(200, "登陆成功", map);
    }



    /**
     * 根据用户Id查找用户数据表的基本信息
     * */
    @Override
    public UserInfoVO selectUserInfoByUid(String uid) {
        if (StringUtils.isEmpty(uid)){
            throw new BusinessException("invalid_parameter");
        }
        return userInfoMapper.selectUserInfoByUid(uid);
    }



    private String getIp(){
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ipAddress = null;
        try {
            // 获取请求客户端的ip
            ipAddress = request.getHeader("x-forwarded-for");
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
                if (ipAddress.equals("127.0.0.1")||ipAddress.equals("0:0:0:0:0:0:0:1")) {
                    ipAddress = "127.0.0.1";
                }
            }
            // 判断ip是否符合规格
            if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()
                // = 15
                if (ipAddress.indexOf(",") > 0) {
                    ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
                }
            }
        } catch (Exception e) {
            ipAddress="";
        }
        return ipAddress;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResultVO userRegister(String sessionId, RegisterDTO registerDTO) {
        try {
            // 校验码匹配
            if (!registerDTO.getCheckCode().equalsIgnoreCase(redisUtil.getCacheObject(Constants.CHECK_CODE_PRE + sessionId).toString())){
                log.error("sessionID:========================"+sessionId);
                // 验证码不一致
                throw new BusinessException("incorrect_captcha");
            }
            // 根据用户名查询数据
            UserRegister userRegister = userRegisterMapper.selectOne(new QueryWrapper<UserRegister>()
                    .eq("pi_name", registerDTO.getPiName())
                    .eq("del_flag", 0)
                    .select("pi_name", "password", "uid"));
            if (userRegister == null){
                throw new BusinessException("account_not_found");
            }
            // 校验密码
            boolean flag = StringUtil.checkPassword(registerDTO.getPassword(), userRegister.getPassword());
            if (!flag){
                throw new BusinessException("incorrect_password");
            }
            // 获取用户数据
            String uid = userRegister.getUid();
            UserInfo userInfo = userInfoMapper.selectOne(new QueryWrapper<UserInfo>().eq("uid", uid).eq("status", 0));
            if (userInfo == null){
                throw new BusinessException("user_data_not_found");
            }
            // 判断是否有钱包地址
            if (userInfo.getWalletAddress() == null){
                // 创建HD地址
                String walletAddress = HDWalletGenerator.generateHDWallet(userInfo.getId());
                userInfo.setWalletAddress(walletAddress);
                int insert = userInfoMapper.updateById(userInfo);
                if (insert < 1){
                    throw new BusinessException("create_wallet_address_failed");
                }
            }
            UserInfoVO userInfoVO = new UserInfoVO();
            BeanUtils.copyProperties(userInfo,userInfoVO);
            // 生成token
            String jwt = JwtUtil.createJWT(uid);
            //把token响应给前端
            HashMap<String,Object> map = new HashMap<>(1);
            map.put("token",jwt);
            map.put("user",userInfoVO);
            return new ResponseResultVO(200,"登陆成功",map);
        } finally {
            // 无论是否成功，都要令上一次的验证码失效
            redisUtil.deleteObject(Constants.CHECK_CODE_PRE + sessionId);
        }
    }

    /**
     * 根据用户Id更改用户数据表的信息
     * */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUserInfoByUid(UserInfoVO userInfoVO) {
        if (userInfoVO==null){
            throw new BusinessException("invalid_parameter");
        }
        String userName = userInfoVO.getUserName();
        String uid = userInfoVO.getUid();
        int result = userInfoMapper.update(null, new UpdateWrapper<UserInfo>()
                .eq("uid", uid)
                .set(!"".equals(userInfoVO.getCountry()),"country",userInfoVO.getCountry())
                .set(userInfoVO.getLanguage() != null ,"language", userInfoVO.getLanguage())
                .set(!"".equals(userInfoVO.getEmail()) && userInfoVO.getEmail() != null,"email", userInfoVO.getEmail()));

        // 要求网店名和用户名保持一致，如果修改了用户名要求同步网店名
        if (userName != null && !"".equals(userName)){
            int update = itemInfoMapper.update(null, new UpdateWrapper<UserShopInfo>()
                    .eq("uid", uid)
                    .eq("status", 0)
                    .set("shop_name", userName));
            if (update < 1) {
                throw new RuntimeException();
            }
        }
        return result > 0;
    }

    /**
     * 根据用户Id更改用户语言标识
     * */
    @Override
    @Transactional
    public boolean updateLanguageByUid(String uid, String language) {
        if (StringUtils.isEmpty(uid) || StringUtils.isEmpty(language)){
            throw new BusinessException("invalid_parameter");
        }
        int result = userInfoMapper.update(null, new UpdateWrapper<UserInfo>()
                .eq("uid", uid)
                .set("language", language));
        return result > 0;
    }


    /**
     * 根据用户Id更改用户国家标识
     * */
    @Override
    @Transactional
    public boolean updateCountryByUid(String uid, String country) {
        if (StringUtils.isEmpty(uid) || StringUtils.isEmpty(country)){
            throw new BusinessException("invalid_parameter");
        }
        int result = userInfoMapper.update(null, new UpdateWrapper<UserInfo>()
                .eq("uid", uid)
                .set("Country", country));

        return result > 0;
    }

    /**
     * 更改头像
     */
    @Override
    @Transactional
    public boolean uploadUserImage(String userId, MultipartFile file) {
        if (StringUtils.isEmpty(userId)|| file.isEmpty()){
            throw new BusinessException("invalid_parameter");
        }
        List<String> sizeList = new ArrayList<>();
        sizeList.add(ImageConstants.USER_IMAGE_SIZE_SMALL);
        String imageId = FileUploadUtil.allUploadImageData(file, imageMapper, FileUploadUtil.AVATAR,sizeList);
        if ("image_not_approved".equals(imageId)){
            return false;
        }
        // 外键关联目标图片数据
        int update = userInfoMapper.update(null, new LambdaUpdateWrapper<UserInfo>()
                .eq(UserInfo::getUid, userId)
                .set(UserInfo::getUserImage, imageId));
//        //更新网店头像
//        int update1 = shopMapper.update(null, new LambdaUpdateWrapper<Shop>()
//                .eq(Shop::getShopName, userId)
//                .set(Shop::getAvatar, imageId));
        if (update < 1) {
            log.error("外键关联目标图片数据");
            return false;
        }
        return true;
    }

    @Override
    public ItemMinInfoVo getItemInfoByUid(String userId) {
        if (StringUtils.isEmpty(userId)){
            throw new BusinessException("invalid_parameter");
        }
        return itemInfoMapper.getItemInfoByUid(userId);
    }

    @Override
    public String getItemIdByUserId(String userId) {
        if (StringUtils.isEmpty(userId)){
            throw new BusinessException("invalid_parameter");
        }
        return userInfoMapper.getItemIdByUserId(userId);
    }

    /**
     * 根据用户Id判断用户是否能发布实体店
     * */
    @Override
    public Integer releaseShopIsNotById(String uid) {
        if (StringUtils.isEmpty(uid)){
            throw new BusinessException("invalid_parameter");
        }
        return userInfoMapper.selectShopNumber(uid);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean upToVipUser(String userId) {
        if (StringUtils.isEmpty(userId)){
            throw new BusinessException("invalid_parameter");
        }
        int update = userInfoMapper.update(null, new UpdateWrapper<UserInfo>()
                .eq("uid", userId)
                .eq("status", 0)
                .set("level", 1));
        // 将其名下的商店店铺都升级为vip店铺
        shopInfoMapper.update(null, new UpdateWrapper<UserShopInfo>()
                .eq("uid", userId)
                .eq("status", 0)
                .set("membership", 1));
        return update > 0;
    }

    @Override
    public boolean isVipUser(String uid) {
        if (StringUtils.isEmpty(uid)){
            throw new BusinessException("invalid_parameter");
        }
        Long count = userInfoMapper.selectCount(new QueryWrapper<UserInfo>()
                .eq("uid", uid)
                .eq("status", 0)
                .eq("level", 1));
        return count.intValue() == 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertRegisterData(UserRegisterDTO userRegisterDTO) {
        if (userRegisterDTO==null){
            throw new BusinessException("invalid_parameter");
        }
        // 将密码进行BCrypt加密再存到数据库中
        String passWord = userRegisterDTO.getPassword();
        String hashPassword = StringUtil.hashPassword(passWord);
        userRegisterDTO.setPassword(hashPassword);
        UserRegister user = userRegisterMapper.selectOne(new QueryWrapper<UserRegister>()
                .eq("uid", userRegisterDTO.getUid()));
        if (user==null){
            // 插入数据
            int insert = userRegisterMapper.insertRegisterData(userRegisterDTO);
            return insert > 0;
        }
        if (!user.getPassword().equals(hashPassword)){
            throw new BusinessException("incorrect_password");
        }
        // 更新数据
        int update = userRegisterMapper.update(null, new UpdateWrapper<UserRegister>()
                .eq("uid", userRegisterDTO.getUid())
                .set("password", userRegisterDTO.getPassword()));
        return update > 0;
    }

    public String getIp2Region(String ipAddress){


        if ("127.0.0.1".equals(ipAddress) || ipAddress.startsWith("192.168")) {
            return "局域网 ip";
        }
        String dbPath;
        if (searcher == null) {
            try {
                // 加载ip2region 文件
                searcher= Searcher.newWithFileOnly("pipayshop-api/src/main/resources/ipdb/ip2region.xdb");

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        String region = null;
        String errorMessage = null;
        try {
            // 获取地区
            region = searcher.search(ipAddress);
        } catch (Exception e) {
            errorMessage = e.getMessage();
            if (errorMessage != null && errorMessage.length() > 256) {
                errorMessage = errorMessage.substring(0,256);
            }
            e.printStackTrace();
        }
        // 输出 region
        return region;

    }

    public boolean deleteImageByDelFlag() {
        try {
            // 1. 获取需要删除的图片 URL
            List<Image> imagesToDelete = imageMapper.getImagesByDelFlag();
            if (imagesToDelete.isEmpty()) {
                return true;
            }

            // 2. 创建待删除的文件列表
            List<String> objectKeys = new ArrayList<>();
            for (Image image : imagesToDelete) {
                String imageUrl = image.getOriginPath();
                String filePath = getFileNameFromUrl(imageUrl);  // 获取完整路径

                // 3. 将完整路径添加到删除列表
                if (filePath != null && !filePath.isEmpty()) {
                    objectKeys.add(filePath);  // 添加完整路径
                }
            }

            // 4. 删除 OSS 中的图片
            if (!objectKeys.isEmpty()) {
                boolean isDeleted = OssUtil.deleteFiles(objectKeys);
                if (!isDeleted) {
                    throw new BusinessException("部分文件删除失败");
                }
                System.out.println("OSS图片删除成功");
            }

            // 5. 删除数据库中的记录
            imageMapper.deleteImageByDelFlag();

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("OSS旧图片删除失败");
        }
    }

    private String getFileNameFromUrl(String imageUrl) {
        String[] parts = imageUrl.split("/", 5);
        if (parts.length > 4) {
            return String.join("/", Arrays.copyOfRange(parts, 3, parts.length));  // 连接路径部分
        }
        return null;
    }


}
